import uvm_pkg::*;
`include "uvm_macros.svh"

class spt_driver extends uvm_driver #(spt_packet);
	`uvm_component_utils(spt_driver)
	
	virtual spt_interface vif;
	
	function new(string name, uvm_component parent);
		super.new(name,parent);
		`uvm_info(get_type_name(), "spt_driver function new start...", UVM_LOW)
	endfunction: new
	
	function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		if(!uvm_config_db#(virtual spt_interface)::get(this,"","vif",this.vif))begin
			`uvm_error(get_type_name(), "build_phase(): Virtual interface in spt_driver is not configured");
		end
	endfunction: build_phase
	
	task reset();
		@(posedge vif.clk);
		vif.vld <= 1'b0;
		vif.data <= $urandom();
	endtask: reset
	
	task run_phase(uvm_phase phase);
		spt_packet drv_tr;
		uvm_packer packer;
		int cycle;
		int i;
		
		`uvm_info(get_type_name(), "spt_driver run_phase start...", UVM_LOW);
		
		@(posedge vif.rst_n)
		#100ns;
		this.reset();
		
		forever begin
			seq_item_port.get_next_item(req);

			if(!$cast(drv_tr,req))begin
				`uvm_fatal(get_type_name(), "send_stimulus_data(): req is not a spt type or its extension");
			end

			drv_tr.do_pack(packer);
			`uvm_info(get_type_name(),$sformatf("spt_drv output packet: %s",drv_tr.sprint()),UVM_HIGH);

			for(cycle = 0;cycle  < drv_tr.pkt_len;cycle ++)begin
				@(posedge vif.clk);
				vif.vld <= 1'b1;
				vif.data <= drv_tr.pkt_data[cycle];
			end
			
			for(i = 0;i < 3;i ++)begin
				@(posedge vif.clk);
				vif.vld  <= 1'b0;
				vif.data <= $urandom();
			end
			
			seq_item_port.item_done();
		end
	endtask: run_phase
endclass: spt_driver
